﻿using Gasgoo.ShareLibrary.Framework._SerializerProvider;
using Gasgoo.ShareLibrary.Framework.ServiceDefine;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Security.Cryptography;
using System.Text;

public static partial class GasgooUtils
{
    readonly static ConcurrentDictionary<Type, object> typeDefaultValueMap = new ConcurrentDictionary<Type, object>();
    readonly static ConcurrentDictionary<string, string> serverKeyTypeMap = new ConcurrentDictionary<string, string>();
    readonly static NewtonJsonSerializerSettings serializerSettings = new NewtonJsonSerializerSettings();
    readonly static object _lock = new object();
    readonly static object _lockdefault = new object();

    public static object DefaultForType(Type targetType)
    {
        if (typeDefaultValueMap.ContainsKey(targetType))
        {
            return typeDefaultValueMap[targetType];
        }

        lock (_lockdefault)
        {
            if (typeDefaultValueMap.ContainsKey(targetType))
            {
                return typeDefaultValueMap[targetType];
            }
            else
            {
                var value = targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
                typeDefaultValueMap.TryAdd(targetType, value);
                return typeDefaultValueMap[targetType];
            }
        }
    }

    public static string GetKeyTypeOfClass(string className)
    {
        if (serverKeyTypeMap.ContainsKey(className))
        {
            return serverKeyTypeMap[className];
        }

        lock (_lock)
        {
            if (serverKeyTypeMap.ContainsKey(className))
            {
                return serverKeyTypeMap[className];
            }
            else
            {
                string keyType = string.Empty;
                Type type = Type.GetType(className);

                if (type == null)
                {
                    serverKeyTypeMap.TryAdd(className, keyType);
                    return serverKeyTypeMap[className];
                }

                if (type.GetInterface(nameof(GasgooServiceWithIntegerKey)) != null)
                {
                    keyType = "long";
                }
                else if (type.GetInterface(nameof(GasgooServiceWithGuidKey)) != null)
                {
                    keyType = "guid";
                }
                else if (type.GetInterface(nameof(GasgooServiceWithStringKey)) != null)
                {
                    keyType = "string";
                }
                else if (type.GetInterface(nameof(GasgooServiceWithIntegerCompoundKey)) != null)
                {
                    keyType = "long-string";
                }
                else if (type.GetInterface(nameof(GasgooServiceWithGuidCompoundKey)) != null)
                {
                    keyType = "guid-string";
                }

                serverKeyTypeMap.TryAdd(className, keyType);
                return serverKeyTypeMap[className];
            }
        }
    }

    public static string SerializeObject(object value)
    {
        if (value == null)
            return string.Empty;

        return JsonConvert.SerializeObject(value, serializerSettings.Create());
    }

    public static T DeserializeObject<T>(string value)
    {
        if (string.IsNullOrEmpty(value))
            return default(T);

        return JsonConvert.DeserializeObject<T>(value, serializerSettings.Create());
    }

    public static object DeserializeObject(string value, Type type)
    {
        if (string.IsNullOrEmpty(value))
            return DefaultForType(type);

        return JsonConvert.DeserializeObject(value, type, serializerSettings.Create());
    }

    public static Guid ToGuid(string input)
    {
        using (MD5 md5Hash = MD5.Create())
        {
            var computehash = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
            return new Guid(computehash);
            //data = BitConverter.ToString(computehash, 4, 8);
            //data = data.Replace("-", "");
        }

        //Encoding.Default.GetBytes(data).CopyTo(bytes, 0);
        //return new Guid(bytes);
    }

    public static T Create<T>(IServiceProvider services, string providerName) where T : class
    {
        return ActivatorUtilities.CreateInstance<T>(services, providerName);
    }

    public static Func<IServiceProvider, string, T> Create<T>(T ins) where T : class
        => (IServiceProvider services, string providerName) => ins;
}
